home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 September / macformat-041.iso / mac / Shareware City / Graphics / MacSPD / Sources / drv_ibm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-15  |  19.9 KB  |  817 lines  |  [TEXT/MMCC]

  1. /* drvr_zrtc.c - Zortech Flash Graphics specific version of display routines. */
  2.  
  3. /*
  4.  * Modified: 17 Mar 1993
  5.  *           Eduard [esp] Schwan
  6.  *           Passed bg_color to display_init
  7. */
  8. #include <stdlib.h> /* Needed for malloc */
  9. #include <stdio.h>  /* Needed for stderr */
  10.  
  11. /* Video resolutions and mode starting numbers */
  12. #define VIDEO_RESOLUTIONS 5
  13. #define FIRST_8BIT_MODE 1
  14. #define FIRST_HICOLOR_MODE (FIRST_8BIT_MODE + VIDEO_RESOLUTIONS)
  15. #define FIRST_16BIT_MODE (FIRST_HICOLOR_MODE + VIDEO_RESOLUTIONS)
  16. #define FIRST_TRUECOLOR_MODE  (FIRST_16BIT_MODE + VIDEO_RESOLUTIONS)
  17. #define FIRST_4BIT_MODE (FIRST_TRUECOLOR_MODE + VIDEO_RESOLUTIONS)
  18.  
  19. #include <io.h>
  20. #if !defined( MAC )
  21. #include <dos.h>
  22. #if defined( __GNUC__ )
  23. #include <pc.h>
  24. #define MK_FP(seg, ofs) ((void *)(0xE0000000 + ((seg)<<4) + ofs))
  25. #define FP_OFF(ptr) (unsigned short)(ptr)
  26. #define FP_SEG(ptr) (unsigned short)(((unsigned long)ptr >> 16) & 0x0FFF)
  27. #define segread(x) (void)(x)
  28. #define getch() getkey()
  29. #define __far
  30. #define outp( portid,v )  outportb( portid,v )
  31. #define inp( portid ) inportb( portid )
  32. #elif defined( DOS386 )
  33. #include <conio.h>
  34. #else
  35. #define __far
  36. #endif
  37. #endif
  38. #include "def.h"
  39. #include "drv.h"
  40.  
  41. #define TEST_ABORT if (kbhit() && getch() == 27) { display_close(0); exit(1); }
  42.  
  43. typedef struct {
  44.    unsigned char bytes;
  45.    unsigned char byte[3];
  46.    } quantized_color;
  47.  
  48. static quantized_color black1 = {1, {0, 0, 0}};
  49. static quantized_color black2 = {2, {0, 0, 0}};
  50. static quantized_color black3 = {3, {0, 0, 0}};
  51.  
  52. int Pallette_Start = 0;      /* Pallette entries start at 0 */
  53. int Pallette_Flag = 1;       /* Use 884 pallette */
  54. int Display_Flag = 3;        /* Use 800x600 256 color VESA mode */
  55. int Reset_Display_Flag = 1;  /* Turn on the requested video mode */
  56.  
  57. /* Define the top right, the width, and the length of usuable display area */
  58. int Display_x0 = -1, Display_y0 = -1;
  59. int Display_xl = -1, Display_yl = -1;
  60.  
  61. /* The amount of squashing required to get the image resolution to fit into
  62.    the available screen space */
  63. static float X_Display_Scale = 1.0;
  64. static float Y_Display_Scale = 1.0;
  65.  
  66. /* Format of VESA global information */
  67. struct VgaInfoBlock   {
  68.   unsigned char      VESASignature[4];
  69.   unsigned char      VESAVersion;
  70.   unsigned char      VESARevision;
  71.   unsigned short     OEMStringPtrOff;
  72.   unsigned short     OEMStringPtrSeg;
  73.   unsigned char      Capabilities[4];
  74.   unsigned short     VideoModePtrOff;
  75.   unsigned short     VideoModePtrSeg;
  76.   };
  77.  
  78. /* Format of the information for individual VESA display modes */
  79. struct ModeInfoBlock   {
  80.   unsigned short ModeAttributes;
  81.   unsigned char  WinAAttributes;
  82.   unsigned char  WinBAttributes;
  83.   unsigned short WinGranularity;
  84.   unsigned short WinSize;
  85.   unsigned short WinASegment;
  86.   unsigned short WinBSegment;
  87.   unsigned short WinFunctPtrOff;
  88.   unsigned short WinFunctPtrSeg;
  89.   unsigned short BytesPerScanLine;
  90.  
  91.   /* the remainder of this structure is optional */
  92.  
  93.   unsigned short XResolution;
  94.   unsigned short YResolution;
  95.   unsigned char XCharSize;
  96.   unsigned char YCharSize;
  97.   unsigned char NumberOfPlanes;
  98.   unsigned char BitsPerPixel;
  99.   unsigned char NumberOfBanks;
  100.   unsigned char MemoryModel;
  101.   unsigned char BankSize;
  102. };
  103.  
  104. static unsigned offx = 0;
  105. static unsigned offy = 0;
  106. static unsigned maxx = 800;
  107. static unsigned maxy = 600;
  108. static unsigned line_length = 800;
  109. static unsigned screen_maxx = 800;
  110. static unsigned screen_maxy = 600;
  111. static unsigned long granularity = 65536;
  112.  
  113. typedef unsigned char pallette_array[256][3];
  114. static pallette_array *pallette = NULL;
  115.  
  116. static int EGA_colors[16][3] =
  117.    {{  0,  0,  0}, {  0,  0,255}, {  0,255,  0}, {  0,127,127},
  118.     {255,  0,  0}, {127,  0,127}, {127,127,  0}, { 85, 85, 85},
  119.     {170,170,170}, {127,127,255}, {127,255,127}, {  0,255,255},
  120.     {255,127,127}, {255,  0,255}, {255,255,  0}, {255,255,255}};
  121. static int EGA_remap[16] =
  122.    {0,  6,  5,  4,  3,  2, 1,  7,
  123.     8, 14, 13, 12, 11, 10, 9, 15};
  124.  
  125. /* Global variables to keep track of VESA calls */
  126. static struct ModeInfoBlock VESAModeInfo;
  127.  
  128. #if defined( DOS386 )
  129. static short real_buf[2];
  130. /* Pointer to real memory for looking at VESA information */
  131. static unsigned char __far *real_ptr;
  132.  
  133. /* Ask the dos extender where to communicate with real mode BIOS calls */
  134. static void
  135. find_real_buf()
  136. {
  137.    struct SREGS sregs;
  138.    union REGS regs;
  139.  
  140.    regs.x.ax = 0x250d;
  141.    segread(&sregs);
  142.    int86x(0x21, ®s, ®s, &sregs);
  143.  
  144.    *((unsigned *)&real_buf) = regs.e.ebx;
  145.    real_ptr = MK_FP(sregs.es, regs.e.edx);
  146. }
  147.  
  148. #elif defined( __GNUC__ )
  149. static int real_buf[2];
  150. static unsigned char __far *real_ptr;
  151.  
  152. void
  153. find_real_buf()
  154. {
  155.    static unsigned char *memptr = (unsigned char *)0xE0000000;
  156.    static unsigned char buf[0x1000];
  157.  
  158.    union REGS reg;
  159.    unsigned char *p, *filename;
  160.    int i, occur = 0;
  161.  
  162.    strcpy(buf, "tmpXXXXX");
  163.    filename = mktemp(buf);
  164.  
  165.    for (p = &memptr[0xA0000-1-strlen((char *)buf)]; p != memptr; p--)
  166.       if (buf[0] == *p && strcmp((char *)buf, (char *)p) == 0) {
  167.      real_ptr = p;
  168.      occur++;
  169.      }
  170.  
  171.    if (!occur) {
  172.       fprintf(stderr, "Video init failure");
  173.       exit(1);
  174.       }
  175.  
  176.    reg.h.ah = 0x1A;
  177.    reg.x.dx = (int)buf;
  178.    int86(0x21, ®, ®);
  179.  
  180.    reg.h.ah = 0x4E;
  181.    reg.x.dx = (int)"*.*";
  182.    int86(0x21, ®, ®);
  183.    real_buf[0] = (reg.x.dx & 0xFFFF) - 43;
  184.  
  185.    getcwd(buf, sizeof(buf));
  186.    if ((i = strlen(buf)) < 2) i = 2;
  187.    real_ptr = real_ptr - 3 - i;
  188. }
  189. #endif
  190.  
  191. static void
  192. bios_putpixel(int x, int y, int color)
  193. {
  194.    union REGS reg;
  195.  
  196.    reg.h.ah = 0x0c;
  197.    reg.h.al = color;
  198.    reg.h.bh = 0;
  199.    reg.x.cx = x;
  200.    reg.x.dx = y;
  201.    int86(0x10, ®, ®);
  202. }
  203.  
  204. static void
  205. setvideomode(int mode)
  206. {
  207.    union REGS reg;
  208.    reg.h.ah = 0;
  209.    reg.h.al = mode;
  210.    int86(0x10, ®, ®);
  211. }
  212.  
  213. static int
  214. setvesabank(int bank)
  215. {
  216.    static int current_bank = -1;
  217.    union REGS reg;
  218.  
  219.    if (bank != current_bank) {
  220.       current_bank = bank;
  221.       reg.x.ax = 0x4F05;
  222.       reg.x.bx = 0;
  223.       reg.x.dx = bank;
  224.       int86(0x10, ®, ®);
  225.       return (reg.x.ax == 0x004f ? 1 : 0);
  226.       }
  227.    return 1;
  228. }
  229.  
  230. static int
  231. setvesamode(int mode, int clear)
  232. {
  233.    union REGS regs;
  234.    struct SREGS sregs;
  235.    struct ModeInfoBlock *VgaPtr = &VESAModeInfo;
  236.    unsigned i;
  237.  
  238.    /* Call VESA function 1 to get mode info */
  239.    regs.h.ah = 0x4f;
  240.    regs.h.al = 0x01;
  241.    regs.x.cx = mode;
  242. #if defined( DOS386 )
  243.    regs.x.di = real_buf[0];
  244.    segread(&sregs);
  245.    sregs.es  = real_buf[1];
  246.    int86x_real(0x10, ®s, ®s, &sregs);
  247.    if (regs.h.al != 0x4f || regs.h.ah != 0)
  248.       return 0;
  249.    for (i=0; i<sizeof(struct ModeInfoBlock); i++)
  250.       ((unsigned char *)VgaPtr)[i] = real_ptr[i];
  251. #elif defined( __GNUC__ )
  252.    regs.x.di = real_buf[0];
  253.    int86x(0x10, ®s, ®s, &sregs);
  254.    if (regs.h.al != 0x4f || regs.h.ah != 0)
  255.       return 0;
  256.    for (i=0; i<sizeof(struct ModeInfoBlock); i++)
  257.       ((unsigned char *)VgaPtr)[i] = real_ptr[i];
  258. #else
  259.    regs.x.di = FP_OFF(VgaPtr);
  260.    sregs.es  = FP_SEG(VgaPtr);
  261.    int86x(0x10, ®s, ®s, &sregs);
  262.    if (regs.h.al != 0x4f || regs.h.ah != 0)
  263.       return 0;
  264. #endif
  265.  
  266.    /* The mode is supported - save useful information and initialize
  267.       the graphics display */
  268.    line_length = VgaPtr->BytesPerScanLine;
  269.    granularity = ((unsigned long)VgaPtr->WinGranularity) << 10;
  270.    screen_maxx = VgaPtr->XResolution;
  271.    screen_maxy = VgaPtr->YResolution;
  272.  
  273.    if (Reset_Display_Flag) {
  274.       /* Now go set the video adapter into the requested mode */
  275.       regs.h.ah = 0x4f;
  276.       regs.h.al = 0x02;
  277.       regs.x.bx = mode;
  278.       int86(0x10, ®s, ®s);
  279.       return (regs.h.al == 0x4f && regs.h.ah == 0x00 ? 1 : 0);
  280.       }
  281. }
  282.  
  283. /* Set a 256 entry pallette with the values given in "palbuf". */
  284. static void
  285. setmany(unsigned char palbuf[256][3], int start, int count)
  286. {
  287.    unsigned i, j;
  288.  
  289.    for (i=0,j=start;i<count;i++,j++) {
  290.       outp(0x3c8, j);
  291.       outp(0x3c9, palbuf[i][0]);
  292.       outp(0x3c9, palbuf[i][1]);
  293.       outp(0x3c9, palbuf[i][2]);
  294.       }
  295. }
  296.  
  297. /* Make space for a pallette & make a 332 color map */
  298. static void
  299. pallette_init()
  300. {
  301.     unsigned i, r, g, b;
  302.  
  303.     if (pallette == NULL) {
  304.     pallette = malloc(sizeof(pallette_array));
  305.     if (pallette == NULL) {
  306.         fprintf(stderr, "Failed to allocate pallette array\n");
  307.         exit(1);
  308.     }
  309.     }
  310.  
  311.     i = 0;
  312.     for (r=0;r<8;r++)
  313.     for (g=0;g<8;g++)
  314.         for (b=0;b<4;b++) {
  315.            (*pallette)[i][0] = r << 3;
  316.            (*pallette)[i][1] = g << 3;
  317.            (*pallette)[i][2] = b << 4;
  318.            i++;
  319.         }
  320.     setmany(*pallette, 0, 256);
  321. }
  322.  
  323. static void
  324. quantize_4bit(COORD3 color, quantized_color *qcolor)
  325. {
  326.    unsigned char r, g;
  327.    float d;
  328.  
  329.    qcolor->bytes = 1;
  330.  
  331.    /* EGA colors */
  332.    d = 0.5;
  333.    r = 0;
  334.    if (color[0] + color[1] - color[2] > d)
  335.       r |= 0x01;
  336.    if (color[0] - color[1] + color[2] > d)
  337.       r |= 0x02;
  338.    if (-color[0] + color[1] + color[2] > d)
  339.       r |= 0x04;
  340.    d = 1.5;
  341.    g = 0x08;
  342.    if (r == 0) {
  343.       d = 0.5;
  344.       g = 0x07;
  345.       }
  346.    else if (r == 7) {
  347.       d = 2.5;
  348.       r = 0x08;
  349.       g = 0x07;
  350.       }
  351.    if (color[0] + color[1] + color[2] > d)
  352.       r |= g;
  353.    qcolor->byte[0] = EGA_remap[r];
  354. }
  355.  
  356. static void
  357. quantize(color, qcolor)
  358.     COORD3 color;
  359.     quantized_color *qcolor;
  360. {
  361.    int i;
  362.    unsigned r, g, b;
  363.  
  364.    i = 255.0 * color[Z];
  365.    if (i<0) i=0;
  366.    else if (i>=256) i = 255;
  367.    b = (unsigned char)i;
  368.  
  369.    i = 255.0 * color[Y];
  370.    if (i<0) i=0;
  371.    else if (i>=256) i = 255;
  372.    g = (unsigned char)i;
  373.  
  374.    i = 255.0 * color[X];
  375.    if (i<0) i=0;
  376.    else if (i>=256) i = 255;
  377.    r = (unsigned char)i;
  378.  
  379.    /* Ignore the resolution and make the display 640x480 hicolor colors. */
  380.    if (Display_Flag >= FIRST_4BIT_MODE &&
  381.        Display_Flag <  FIRST_4BIT_MODE + VIDEO_RESOLUTIONS) {
  382.       qcolor->bytes = 1;
  383.       quantize_4bit(color, qcolor);
  384.       qcolor->byte[0] += Pallette_Start;
  385.       }
  386.    else if (Display_Flag >= FIRST_8BIT_MODE &&
  387.        Display_Flag <  FIRST_8BIT_MODE + VIDEO_RESOLUTIONS) {
  388.       qcolor->bytes = 1;
  389.       switch (Pallette_Flag) {
  390.       case 3:
  391.      quantize_4bit(color, qcolor);
  392.      break;
  393.       case 2:
  394.      /* 666 */
  395.      qcolor->byte[0] = 6 * (6 * (r / 51) + (g / 51)) + b / 51;
  396.      break;
  397.       case 1:
  398.      /* 884 */
  399.      qcolor->byte[0] = (r & 0xE0) | ((g & 0xE0) >> 3) | (b >> 6);
  400.      break;
  401.       default:
  402.      /* Greyscale */
  403.      qcolor->byte[0] = (r>g?(r>b?r>>2:b>>2):(g>b?g>>2:b>>2));
  404.      }
  405.       qcolor->byte[0] += Pallette_Start;
  406.       }
  407.    else if (Display_Flag >= FIRST_HICOLOR_MODE &&
  408.         Display_Flag <  FIRST_HICOLOR_MODE + VIDEO_RESOLUTIONS) {
  409.       /* Hicolor, add bits together */
  410.       qcolor->bytes = 2;
  411.       qcolor->byte[1] = ((r >> 1) & 0x7c) | (g >> 6);
  412.       qcolor->byte[0] = ((g << 2) & 0xe0) | (b >> 3);
  413.       }
  414.    else if (Display_Flag >= FIRST_16BIT_MODE &&
  415.         Display_Flag <  FIRST_16BIT_MODE + VIDEO_RESOLUTIONS) {
  416.       /* Hicolor, add bits together */
  417.       qcolor->bytes = 2;
  418.       qcolor->byte[1] = (r & 0xf8) | (g >> 5);
  419.       qcolor->byte[0] = ((g << 2) & 0xe0) | (b >> 3);
  420.       }
  421.    else if (Display_Flag >= FIRST_TRUECOLOR_MODE &&
  422.         Display_Flag <  FIRST_TRUECOLOR_MODE + VIDEO_RESOLUTIONS) {
  423.       /* Truecolor modes, use quantized pixels */
  424.       qcolor->bytes = 3;
  425.       qcolor->byte[2] = r;
  426.       qcolor->byte[1] = g;
  427.       qcolor->byte[0] = b;
  428.       }
  429.    else {
  430.       display_close(0);
  431.       fprintf(stderr, "Bad display mode in quantize");
  432.       exit(1);
  433.       }
  434. }
  435.  
  436. static void
  437. plotpoint(int x, int y, quantized_color *color)
  438. {
  439.    unsigned char __far *fp;
  440.    unsigned long fpa, fpb;
  441.    unsigned bank;
  442.    int i;
  443.  
  444.    /* Don't plot points outside the screen boundaries */
  445.    if (x < 0 || x >= screen_maxx) return;
  446.    if (y < 0 || y >= screen_maxy) return;
  447.  
  448. #if defined( BIOS_DRAW_ONLY )
  449.    /* Have to do things a little bit differently in 16 color modes */
  450.    bios_putpixel(x, y, color->byte[0]);
  451. #else
  452.    fpa = (unsigned long)line_length * y + (x * color->bytes);
  453.    for (i=0;i<color->bytes;i++,fpa++) {
  454.       if (Display_Flag > 1) {
  455.      /* Only have more than 64K pixels in VESA modes */
  456.      bank = fpa / granularity;
  457.      setvesabank(bank);
  458.      }
  459.       fpb = fpa % granularity;
  460. #if defined( DOS386 )
  461.       fp = MK_FP(_x386_zero_base_selector, 0xA0000 + fpb);
  462. #elif defined( __GNUC__ )
  463.       fp = (unsigned char *)MK_FP(0xA000, (unsigned int)fpb);
  464. #else
  465.       fp = (void *)MK_FP(0xA000, fpb);
  466. #endif
  467.       *fp = color->byte[i];
  468.       }
  469. #endif
  470. }
  471.  
  472. void
  473. display_clear(void)
  474. {
  475.    unsigned i, j;
  476.  
  477.    if (Display_Flag >= 1) {
  478.       /* clear the display the hard way, a pixel at a time. */
  479.       setvesabank(0);
  480.       for (i=offy;i<maxy;i++)
  481.      for (j=offx;j<maxx;j++)
  482.         if (Display_Flag < FIRST_HICOLOR_MODE)
  483.            plotpoint(j, i, &black1);
  484.         else if (Display_Flag < FIRST_TRUECOLOR_MODE)
  485.            plotpoint(j, i, &black2);
  486.         else
  487.            plotpoint(j, i, &black3);
  488.       }
  489. }
  490.  
  491. void
  492. display_init(xres, yres, bk_color)
  493.     int xres, yres;
  494.     COORD3 bk_color;
  495. {
  496.    static int init_flag = 0;
  497.    int sflag, x1, y1;
  498.    COORD3 white;
  499.  
  500.    sflag = 0; /* No subscreen window */
  501.    if (Display_x0 < 0) Display_x0 = 0; else sflag = 1;
  502.    if (Display_y0 < 0) Display_y0 = 0; else sflag = 1;
  503.    if (Display_xl < 0) Display_xl = xres; else sflag = 1;
  504.    if (Display_yl < 0) Display_yl = yres; else sflag = 1;
  505.  
  506.    /* Now go set up the display */
  507.    if (init_flag)
  508.       display_clear();
  509.    else {
  510. #if defined( DOS386 ) || defined( __GNUC__ )
  511.       if (Display_Flag != FIRST_8BIT_MODE)
  512.      find_real_buf();
  513. #endif
  514.       init_flag = 1;
  515.       switch (Display_Flag) {
  516.  
  517.      /* Truecolor video modes */
  518.      case FIRST_TRUECOLOR_MODE+4:
  519.         if (setvesamode(0x11b, 0)) {
  520.            Display_Flag = FIRST_TRUECOLOR_MODE+4;
  521.            break;
  522.            }
  523.      case FIRST_TRUECOLOR_MODE+3:
  524.         if (setvesamode(0x118, 0)) {
  525.            Display_Flag = FIRST_TRUECOLOR_MODE+3;
  526.            break;
  527.            }
  528.      case FIRST_TRUECOLOR_MODE+2:
  529.         if (setvesamode(0x115, 0)) {
  530.            Display_Flag = FIRST_TRUECOLOR_MODE+2;
  531.            break;
  532.            }
  533.      case FIRST_TRUECOLOR_MODE+1:
  534.         if (setvesamode(0x112, 0)) {
  535.            Display_Flag = FIRST_TRUECOLOR_MODE+1;
  536.            break;
  537.            }
  538.      case FIRST_TRUECOLOR_MODE:
  539.         if (setvesamode(0x10f, 0)) {
  540.            Display_Flag = FIRST_TRUECOLOR_MODE;
  541.            break;
  542.            }
  543.  
  544.      /* Hicolor video modes */
  545.      case FIRST_16BIT_MODE+4:
  546.         if (setvesamode(0x11a, 0)) {
  547.            Display_Flag = FIRST_16BIT_MODE+4;
  548.            break;
  549.            }
  550.      case FIRST_HICOLOR_MODE+4:
  551.         if (setvesamode(0x119, 0)) {
  552.            Display_Flag = FIRST_HICOLOR_MODE+4;
  553.            break;
  554.            }
  555.      case FIRST_16BIT_MODE+3:
  556.         if (setvesamode(0x117, 0)) {
  557.            Display_Flag = FIRST_16BIT_MODE+3;
  558.            break;
  559.            }
  560.      case FIRST_HICOLOR_MODE+3:
  561.         if (setvesamode(0x116, 0)) {
  562.            Display_Flag = FIRST_HICOLOR_MODE+3;
  563.            break;
  564.            }
  565.      case FIRST_16BIT_MODE+2:
  566.         if (setvesamode(0x114, 0)) {
  567.            Display_Flag = FIRST_16BIT_MODE+2;
  568.            break;
  569.            }
  570.      case FIRST_HICOLOR_MODE+2:
  571.         if (setvesamode(0x113, 0)) {
  572.            Display_Flag = FIRST_HICOLOR_MODE+2;
  573.            break;
  574.            }
  575.      case FIRST_16BIT_MODE+1:
  576.         if (setvesamode(0x111, 0)) {
  577.            Display_Flag = FIRST_16BIT_MODE+1;
  578.            break;
  579.            }
  580.      case FIRST_HICOLOR_MODE+1:
  581.         if (setvesamode(0x110, 0)) {
  582.            Display_Flag = FIRST_HICOLOR_MODE+1;
  583.            break;
  584.            }
  585.      case FIRST_16BIT_MODE:
  586.         if (setvesamode(0x10e, 0)) {
  587.            Display_Flag = FIRST_16BIT_MODE;
  588.            break;
  589.            }
  590.      case FIRST_HICOLOR_MODE:
  591.         if (setvesamode(0x10d, 0)) {
  592.            Display_Flag = FIRST_HICOLOR_MODE;
  593.            break;
  594.            }
  595.  
  596.      /* Now try the 8 bit modes, starting at the most extreme */
  597.      case FIRST_8BIT_MODE+4:
  598.         if (setvesamode(0x107, 0)) {
  599.            Display_Flag = FIRST_8BIT_MODE+4;
  600.            pallette_init();
  601.            break;
  602.            }
  603.      case FIRST_8BIT_MODE+3:
  604.         if (setvesamode(0x105, 0)) {
  605.            Display_Flag = FIRST_8BIT_MODE+3;
  606.            pallette_init();
  607.            break;
  608.            }
  609.      case FIRST_8BIT_MODE+2:
  610.         if (setvesamode(0x103, 0)) {
  611.            Display_Flag = FIRST_8BIT_MODE+2;
  612.            pallette_init();
  613.            break;
  614.            }
  615.      case FIRST_8BIT_MODE+1:
  616.         if (setvesamode(0x101, 0)) {
  617.            Display_Flag = FIRST_8BIT_MODE+1;
  618.            pallette_init();
  619.            break;
  620.            }
  621.      case FIRST_8BIT_MODE:
  622.         setvideomode(19);
  623.         screen_maxx = 320;
  624.         screen_maxy = 200;
  625.         Display_Flag = FIRST_8BIT_MODE;
  626.         pallette_init();
  627.         break;
  628.  
  629.      case FIRST_4BIT_MODE+1:
  630.         setvideomode(18);
  631.         screen_maxx = 640;
  632.         screen_maxy = 480;
  633.         Pallette_Flag = 3; /* Must be 4 bit pallette */
  634.         Display_Flag = FIRST_4BIT_MODE+1;
  635.         break;
  636.  
  637.      case FIRST_4BIT_MODE:
  638.         setvideomode(13);
  639.         screen_maxx = 320;
  640.         screen_maxy = 200;
  641.         Pallette_Flag = 3; /* Must be 4 bit pallette */
  642.         Display_Flag = FIRST_4BIT_MODE;
  643.         break;
  644.  
  645.      default:
  646.         fprintf(stderr, "Failed to set video mode: %d\n", Display_Flag);
  647.         exit(1);
  648.         }
  649.      }
  650.  
  651.    /* Do some conditioning on the screen window to ensure it doesn't cause
  652.       pixels to be generated off screen */
  653.    x1 = Display_x0 + Display_xl;
  654.    y1 = Display_y0 + Display_yl;
  655.    if (x1 >= screen_maxx) { Display_xl = screen_maxx - Display_x0; }
  656.    if (y1 >= screen_maxy) { Display_yl = screen_maxy - Display_y0; }
  657.  
  658.    /* If there is a rendering subwindow of the screen that we should
  659.       be working in.  If so, then set the scaling values appropriately. */
  660.    if (sflag) {
  661.       offx = Display_x0;
  662.       offy = Display_y0;
  663.       maxx = Display_x0 + Display_xl;
  664.       maxy = Display_y0 + Display_yl;
  665.       }
  666.    else {
  667.       offx = 0;
  668.       offy = 0;
  669.       maxx = screen_maxx;
  670.       maxy = screen_maxy;
  671.       }
  672.  
  673.    if (xres > Display_xl)
  674.       X_Display_Scale = (float)Display_xl / (float)xres;
  675.    else
  676.       X_Display_Scale = 1.0;
  677.    if (yres > Display_yl)
  678.       Y_Display_Scale = (float)Display_yl / (float)yres;
  679.    else
  680.       Y_Display_Scale = 1.0;
  681.    if (X_Display_Scale < Y_Display_Scale)
  682.       Y_Display_Scale = X_Display_Scale;
  683.    else if (Y_Display_Scale < X_Display_Scale)
  684.       X_Display_Scale = Y_Display_Scale;
  685.  
  686.     /* Outline the actual "visible" display area in the window */
  687.     SET_COORD3(white, 1.0, 1.0, 1.0);
  688.     display_line(0, 0, 0, yres, white);
  689.     display_line(0, yres,  xres,  yres, white);
  690.     display_line(xres, yres, xres,  0, white);
  691.     display_line(xres, 0,  0, 0, white);
  692. }
  693.  
  694. void
  695. display_close(int wait_flag)
  696. {
  697.     union REGS regs;
  698.  
  699.    if (wait_flag) {
  700. #if !defined( _WINDOWS )
  701.       while (!kbhit()) ;
  702. #endif
  703.       if (!getch()) getch();
  704.       }
  705.  
  706.    if (pallette != NULL) {
  707.       free(pallette);
  708.       pallette = NULL;
  709.       }
  710.  
  711.    /* Go back to standard text mode */
  712.    regs.x.ax = 0x0003;
  713.    int86(0x10, ®s, ®s);
  714.  
  715.    return;
  716. }
  717.  
  718. void
  719. display_plot(x, y, color)
  720.     int x, y;
  721.     COORD3 color;
  722. {
  723.    quantized_color qcolor;
  724.  
  725.    x = offx + X_Display_Scale * x;
  726.    y = offy + Y_Display_Scale * y;
  727.  
  728.    quantize(color, &qcolor);
  729.    plotpoint(x, y, &qcolor);
  730. }
  731.  
  732. /* Draw a line between two points */
  733. static void
  734. line2d(int x1, int y1, int x2, int y2, quantized_color *qcolor)
  735. {
  736.    int d1, x, y;
  737.    int ax, ay;
  738.    int sx, sy;
  739.    int dx, dy;
  740.  
  741.    dx = x2 - x1;
  742.    ax = ABSOLUTE(dx) << 1;
  743.    sx = SGN(dx);
  744.    dy = y2 - y1;
  745.    ay = ABSOLUTE(dy) << 1;
  746.    sy = SGN(dy);
  747.  
  748.    x = x1;
  749.    y = y1;
  750.  
  751.    plotpoint(x, y, qcolor);
  752.    if (ax > ay) {
  753.       /* x dominant */
  754.       d1 = ay - (ax >> 1);
  755.       for (;;) {
  756.      if (x==x2) return;
  757.      if (d1>=0) {
  758.         y += sy;
  759.         d1 -= ax;
  760.         }
  761.      x += sx;
  762.      d1 += ay;
  763.      plotpoint(x, y, qcolor);
  764.      }
  765.       }
  766.    else {
  767.       /* y dominant */
  768.       d1 = ax - (ay >> 1);
  769.       for (;;) {
  770.      if (y == y2) return;
  771.      if (d1 >= 0) {
  772.         x += sx;
  773.         d1 -= ay;
  774.         }
  775.      y += sy;
  776.      d1 += ax;
  777.      plotpoint(x, y, qcolor);
  778.      }
  779.       }
  780. }
  781.  
  782. void
  783. display_line(x0, y0, x1, y1, color)
  784.     int x0, y0, x1, y1;
  785.     COORD3 color;
  786. {
  787.    quantized_color qcolor;
  788.  
  789. TEST_ABORT
  790.  
  791.    /* Scale from image size to actual screen pixel size */
  792.    x0 = offx + X_Display_Scale * x0;
  793.    y0 = offy + Y_Display_Scale * y0;
  794.    x1 = offx + X_Display_Scale * x1;
  795.    y1 = offy + Y_Display_Scale * y1;
  796.  
  797.    if (x0 < Display_x0)
  798.       x0 = Display_x0;
  799.    else if (x0 >= Display_x0 + Display_xl)
  800.       x0 = Display_x0 + Display_xl - 1;
  801.    if (y0 < Display_y0)
  802.       y0 = Display_y0;
  803.    else if (y0 >= Display_y0 + Display_yl)
  804.       y0 = Display_y0 + Display_yl - 1;
  805.    if (x1 < Display_x0)
  806.       x1 = Display_x0;
  807.    else if (x1 >= Display_x0 + Display_xl)
  808.       x1 = Display_x0 + Display_xl - 1;
  809.    if (y1 < Display_y0)
  810.       y1 = Display_y0;
  811.    else if (y0 >= Display_y0 + Display_yl)
  812.       y1 = Display_y0 + Display_yl - 1;
  813.  
  814.    quantize(color, &qcolor);
  815.    line2d(x0, y0, x1, y1, &qcolor);
  816. }
  817.